/**
 * @class PartnershipVisuals
 * @extends AbstractNodeVisuals
 * @constructor
 * @param {Partnership} node 
 * @param {Number} x 
 * @param {Number} y 
 */
var PartnershipVisuals = Class.create(AbstractNodeVisuals, {

	initialize: function($super, partnership, x, y) {
		$super(partnership, x, y);
		this._childlessShape = null;
		this._childlessStatusLabel = null;
		this._deceasedStatusLabel = null;
		this._junctionShape = editor.getPaper().circle(x, y, PedigreeEditor.attributes.partnershipRadius).attr(PedigreeEditor.attributes.partnershipNode);

		if(editor.isReadOnlyMode()) {
			this._hoverBox = new ReadOnlyHoverbox(partnership, x, y, this.getShapes());
		} else {
			this._hoverBox = new PartnershipHoverbox(partnership, x, y, this.getShapes());
		}
		this.updateIDLabel();

		this._childhubConnection = null;
		this._partnerConnections = null;

		this.updatePartnerConnections();
		this.updateChildhubConnection();
	},

	updateIDLabel: function() {
		var x = this.getX();
		var y = this.getY();
		this._idLabel && this._idLabel.remove();
		this._idLabel = editor.getPaper().text(x, y - 20, editor.DEBUG_MODE ? this.getNode().getID() : "").attr(PedigreeEditor.attributes.dragMeLabel).insertAfter(this._junctionShape.flatten());
	},

	/**
	 *
	 * @method onSetID
	 */
	onSetID: function($super, id) {
		$super(id);
		this.updateIDLabel();
	},

	/**
	 *
	 * @method grow
	 */
	grow: function() {
		if(this.area) return;
		this.area = this.getJunctionShape().clone().flatten().insertBefore(this.getJunctionShape().flatten());
		this.area.attr({
			'fill': 'green',
			stroke: 'none'
		});
		this.area.ot = this.area.transform();
		this.area.animate(Raphael.animation({
			transform: "...S2"
		}, 400, 'bounce'));
	},

	/**
	 *
	 * @method shrink
	 */
	shrink: function() {
		this.area && this.area.remove();
		delete this.area;
	},

	/**
	 *
	 * @method grow
	 */
	markPregnancy: function() {
		if(this.mark) return;
		this.mark = this.getJunctionShape().glow({
			width: 10,
			fill: true,
			opacity: 0.3,
			color: "blue"
		}).insertBefore(this.getJunctionShape().flatten());
	},

	/**
	 *
	 * @method unmark
	 */
	unmarkPregnancy: function() {
		this.mark && this.mark.remove();
		delete this.mark;
	},

	markPermanently: function() {
		if(this.mark2) return;
		this.mark2 = this.getJunctionShape().glow({
			width: 18,
			fill: true,
			opacity: 0.4,
			color: "#ee8d00"
		}).insertBefore(this.getJunctionShape().flatten());
	},
	unmark: function() {
		this.mark2 && this.mark2.remove();
		delete this.mark2;
	},

	/**
	 *
	 * @method getJunctionShape
	 * @return {Raphael.st}
	 */
	getJunctionShape: function() {
		return this._junctionShape;
	},

	/**
	 *
	 * @method getY
	 * @return {Number} The y coordinate
	 */
	getBottomY: function() {
		return this._absoluteY + PedigreeEditor.attributes.partnershipRadius + PedigreeEditor.attributes.childlessLength;
	},

	/**
	 *
	 * @method updatePartnerConnections
	 */

	updatePartnerConnections: function() {
		this._partnerConnections && this._partnerConnections.remove();

		editor.getPaper().setStart();

		var positionedGraph = editor.getGraph();

		var id = this.getNode().getID();
		var consangr = positionedGraph.isConsangrRelationship(id);
		var nodeConsangrPreference = this.getNode().getConsanguinity();
		if(nodeConsangrPreference == "N")
			consangr = false;
		if(nodeConsangrPreference == "Y")
			consangr = true;
		if(nodeConsangrPreference == "E")
			consangr = false;
		if(nodeConsangrPreference == "E") {
			var lineAttr = PedigreeEditor.attributes.consangrPartnershipDotLines;
		} else {
			var lineAttr = consangr ? PedigreeEditor.attributes.consangrPartnershipLines : PedigreeEditor.attributes.partnershipLines;
		}
		var partnerPaths = positionedGraph.getPathToParents(id); 

		var smoothCorners = true;
		var cornerRadius = PedigreeEditor.attributes.curvedLinesCornerRadius;

		for(var p = 0; p < partnerPaths.length; p++) {
			var path = partnerPaths[p];

			var person = path[path.length - 1];
			var finalSegmentInfo = editor.getGraph().getRelationshipLineInfo(id, person);

			var nodePos = editor.getGraph().getPosition(person);
			var finalPosition = editor.convertGraphCoordToCanvasCoord(nodePos.x, nodePos.y);
			var finalYTo = editor.convertGraphCoordToCanvasCoord(0, finalSegmentInfo.attachY).y;
			var yTop = editor.convertGraphCoordToCanvasCoord(0, finalSegmentInfo.verticalY).y;
			var lastBend = ((finalYTo == yTop) && (yTop < this.getY()) && finalSegmentInfo.attachmentPort == 1) ?
				Infinity :
				(finalSegmentInfo.numAttachPorts > 1 ?
					PedigreeEditor.attributes.radius * (1.8 + finalSegmentInfo.numAttachPorts * 0.1 - finalSegmentInfo.attachmentPort * 0.35) :
					PedigreeEditor.attributes.radius * 1.6
				);
			var goesLeft = false;
			var xFrom = this.getX();
			var yFrom = this.getY();
			var xTo = xFrom;
			var yTo = yFrom;
			var prevY = yFrom;
			var prevX = xFrom;
			var vertical = false;
			var wasAngle = false;
			for(var i = 0; i < path.length; i++) {
				var nextNodeOnPath = path[i];

				var nodePos = editor.getGraph().getPosition(nextNodeOnPath);
				var position = editor.convertGraphCoordToCanvasCoord(nodePos.x, nodePos.y);
				if(position.x < xFrom)
					goesLeft = true;
				else if(position.x > xFrom)
					goesLeft = false;

				var newVertical = (prevY != position.y);

				var angled = (prevX != position.x && prevY != position.y);

				var changesDirection = ((vertical && !newVertical) || (!vertical && newVertical)) || angled;

				if(i == path.length - 1 && prevY == yTop) {
					angled = false;
					changesDirection = (xFrom != xTo || yFrom != yTo);
					newVertical = false;
				}

				if(i == 0 && goesLeft && this.getNode().getBrokenStatus()) {
					editor.getView().drawLineWithCrossings(id, xFrom, yFrom, xFrom - 16, yFrom, lineAttr, consangr, goesLeft);
					editor.getPaper().path("M " + (xFrom - 29) + " " + (yFrom + 9) + " L " + (xFrom - 15) + " " + (yFrom - 9)).attr(lineAttr).toBack();
					editor.getPaper().path("M " + (xFrom - 24) + " " + (yFrom + 9) + " L " + (xFrom - 10) + " " + (yFrom - 9)).attr(lineAttr).toBack();
					xFrom -= 23;
				}
				if(changesDirection) {
					editor.getView().drawLineWithCrossings(id, xFrom, yFrom, xTo, yTo, lineAttr, consangr, goesLeft);
					xFrom = xTo;
					yFrom = yTo;
				}
				xTo = position.x;
				yTo = (i >= path.length - 2) ? yTop : position.y;
				prevY = position.y;
				prevX = position.x;

				if(smoothCorners && ((!wasAngle && !angled) || (i >= path.length - 2 && path.length > 1))) {
					if(newVertical && !vertical) {
						if(xTo < xFrom) {
							drawCornerCurve(xFrom, yFrom, xFrom - cornerRadius, yFrom - cornerRadius, true, lineAttr, consangr, +2.5, -2.5, -2.5, +2.5);
							xFrom -= cornerRadius;
							yFrom -= cornerRadius;
						} else {
							drawCornerCurve(xFrom, yFrom, xFrom + cornerRadius, yFrom - cornerRadius, true, lineAttr, consangr, +2.5, 2.5, -2.5, -2.5);
							xFrom += cornerRadius;
							yFrom -= cornerRadius;
						}
					} else if(!newVertical && vertical) {
						if(xTo < xFrom) {
							drawCornerCurve(xFrom, yFrom, xFrom - cornerRadius, yFrom - cornerRadius, false, lineAttr, consangr, -2.5, 2.5, 2.5, -2.5);
							xFrom -= cornerRadius;
							yFrom -= cornerRadius;
						} else {
							drawCornerCurve(xFrom, yFrom, xFrom + cornerRadius, yFrom - cornerRadius, false, lineAttr, consangr, 2.5, 2.5, -2.5, -2.5);
							xFrom += cornerRadius;
							yFrom -= cornerRadius;
						}
					} else if(!newVertical) {
						if(i != path.length - 1) {
							if(position.x > xFrom)
								xTo -= cornerRadius;
							else
								xTo += cornerRadius;
						}
					} else {
						yTo += cornerRadius;
					}
				}

				vertical = newVertical;
				wasAngle = angled;
			}

			if(yFrom >= finalPosition.y + cornerRadius * 2) {
				editor.getView().drawLineWithCrossings(id, xFrom, yFrom, xTo, finalYTo, lineAttr, consangr, false);
			} else {
				editor.getView().drawCurvedLineWithCrossings(id, xFrom, yFrom, yTop, xTo, finalYTo, lastBend, lineAttr, consangr, goesLeft);
			}

			var lostContact = !editor.getView().getNode(person).isProband() &&
				editor.getView().getNode(person).getLostContact() &&
				editor.getGraph().isPartnershipRelatedToProband(id);
			if(lostContact) {
				var xCross = goesLeft ? this.getX() - 20 : this.getX() + 20;
				var lineSize = PedigreeEditor.attributes.notInContactLineSize;
				editor.getPaper().path("M " + (xCross) + " " + (this.getY() - lineSize) + " L " + (xCross) + " " + (this.getY() + lineSize)).attr(PedigreeEditor.attributes.noContactLines).toBack();
			}
		}

		this._partnerConnections = editor.getPaper().setFinish().toBack();
		if(this.getNode().getGraphics()) {
			this.getHoverBox().regenerateHandles();
			this.getHoverBox().regenerateButtons();
		}
	},

	/**
	 *
	 * @method updateChildhubConnection
	 */
	updateChildhubConnection: function() {
		this._childhubConnection && this._childhubConnection.remove();

		var twinCommonVerticalPieceLength = PedigreeEditor.attributes.twinCommonVerticalLength;

		var positionedGraph = editor.getGraph();

		var id = this.getNode().getID();

		editor.getPaper().setStart();

		var childlinePos = positionedGraph.getRelationshipChildhubPosition(id);
		var childlineY = editor.convertGraphCoordToCanvasCoord(childlinePos.x, childlinePos.y).y;

		var children = positionedGraph.getRelationshipChildrenSortedByOrder(id);

		var leftmostX = this.getX();
		var rightmostX = this.getX();

		var currentTwinGroup = null;
		var currentTwinGroupCenterX = null;
		var currentIsMonozygothic = false;

		var numPregnancies = 0;

		for(var j = 0; j < children.length; j++) {
			var child = children[j];

			var twinGroupId = positionedGraph.getTwinGroupId(child);
			var groupType = positionedGraph.getGroupType(child);
			//alert(twinGroupId);

			if(twinGroupId != currentTwinGroup) {
				numPregnancies++;

				currentTwinGroup = twinGroupId;

				var allTwins = positionedGraph.getAllTwinsSortedByOrder(child);
				var positionL = editor.getView().getNode(allTwins[0]).getX();
				var positionR = editor.getView().getNode(allTwins[allTwins.length - 1]).getX();
				var positionY = editor.getView().getNode(allTwins[0]).getY();
				currentTwinGroupCenterX = (positionL + positionR) / 2;
				if(allTwins.length == 3)
					currentTwinGroupCenterX = editor.getView().getNode(allTwins[1]).getX();
				editor.getView().drawLineWithCrossings(id, currentTwinGroupCenterX, childlineY, currentTwinGroupCenterX, childlineY + twinCommonVerticalPieceLength, PedigreeEditor.attributes.partnershipLines);

				currentIsMonozygothic = editor.getView().getNode(allTwins[0]).getMonozygotic();
				currentIsUnknownzygotic = editor.getView().getNode(allTwins[0]).getUnknownzygotic();
				if(currentIsMonozygothic) {
					var twinlineY = childlineY + PedigreeEditor.attributes.twinMonozygothicLineShiftY + 30;
					var xIntercept1 = findXInterceptGivenLineAndY(twinlineY, currentTwinGroupCenterX, childlineY + twinCommonVerticalPieceLength, positionL, positionY);
					var xIntercept2 = findXInterceptGivenLineAndY(twinlineY, currentTwinGroupCenterX, childlineY + twinCommonVerticalPieceLength, positionR, positionY);
					//chen.yuguo ,双胞胎中间横线修改
					if(allTwins.length==1){
                        editor.getView().drawLineWithCrossings(id, xIntercept1, twinlineY, xIntercept2, twinlineY, PedigreeEditor.attributes.partnershipLines,false,false,false);
					}else{
						editor.getView().drawLineWithCrossings(id, xIntercept1, twinlineY, xIntercept2, twinlineY, PedigreeEditor.attributes.partnershipLines,false,false,false,99);
					}
					
				} else
				if(currentIsUnknownzygotic) {
					var twinlineY = childlineY + PedigreeEditor.attributes.twinMonozygothicLineShiftY + 10;
					var xIntercept1 = findXInterceptGivenLineAndY(twinlineY, currentTwinGroupCenterX, childlineY + twinCommonVerticalPieceLength, positionL, positionY);
					var xIntercept2 = findXInterceptGivenLineAndY(twinlineY, currentTwinGroupCenterX, childlineY + twinCommonVerticalPieceLength, positionR, positionY);
					var unknownzygoticy = twinlineY + 20;
					var unknownzygoticx = xIntercept1 + (xIntercept2 - xIntercept1) / 2;
					var lineSize = PedigreeEditor.attributes.notInContactLineSize;
					editor.getPaper().text(unknownzygoticx, unknownzygoticy, "?").attr(PedigreeEditor.attributes.unknownzygoticText).toFront();
					editor.getView().drawLineWithCrossings(id, unknownzygoticx, unknownzygoticy, unknownzygoticx, unknownzygoticy, PedigreeEditor.attributes.unknownzygoticLine);
				}

			} else if(twinGroupId == null) {
				numPregnancies++;
				currentIsMonozygothic = false;
			}
			var childX = editor.getView().getNode(child).getX();
			var childY = editor.getView().getNode(child).getY();
			if(currentTwinGroup === null) {
				var topLineX = childX;
			} else if(groupType == "isGroupTwins") {
				//var topLineX = childX;
				var topLineX = currentTwinGroupCenterX;
			} else if(groupType == "isGroupsisters" || groupType == "isGroupbrothers" || groupType == "isGroupunknowns") {
				var topLineX = childX;
			} else {
				var topLineX = currentTwinGroupCenterX;
			}
			if(currentTwinGroup === null) {
				var topLineY = childlineY;
			} else if(groupType == "isGroupTwins") {
				var topLineY = childlineY + twinCommonVerticalPieceLength;
			} else if(groupType == "isGroupsisters" || groupType == "isGroupbrothers" || groupType == "isGroupunknowns") {
				var topLineY = childlineY;
			} else {
				var topLineY = childlineY + twinCommonVerticalPieceLength;
			}
			if(topLineX > rightmostX)
				rightmostX = topLineX;
			if(topLineX < leftmostX)
				leftmostX = topLineX;
			currentIsAdopted = editor.getView().getNode(child).getAdopted();
			if(!currentIsMonozygothic || childX == positionL || childX == positionR) {
				if(currentIsAdopted) {
					editor.getView().drawLineWithCrossings(id, topLineX, topLineY, childX, childY, PedigreeEditor.attributes.adoptedPartnershipDotLines);
				} else {console.log(id, topLineX, topLineY, childX, childY)
					//双胞胎连线问题，chen.yuguo
					editor.getView().drawLineWithCrossings(id, topLineX, topLineY, childX, childY, PedigreeEditor.attributes.partnershipLines,false,false,false,98);
				}
			} else {
				var xIntercept = findXInterceptGivenLineAndY(twinlineY, currentTwinGroupCenterX, childlineY + twinCommonVerticalPieceLength, childX, childY);
				editor.getView().drawLineWithCrossings(id, xIntercept, twinlineY, childX, childY, PedigreeEditor.attributes.partnershipLines);
			}

			var lostContact = editor.getGraph().isChildOfProband(child) && editor.getView().getNode(child).getLostContact();
			if(lostContact) {
				if(twinGroupId == null) {
					var lineSize = PedigreeEditor.attributes.notInContactLineSize;
					editor.getPaper().path("M " + (topLineX - lineSize) + " " + (topLineY + 20) + " L " + (topLineX + lineSize) + " " + (topLineY + 20)).attr(PedigreeEditor.attributes.noContactLines).toBack();
				} else {}
			}
		}
		editor.getView().drawLineWithCrossings(id, leftmostX, childlineY, rightmostX, childlineY, PedigreeEditor.attributes.partnershipLines);
		editor.getView().drawLineWithCrossings(id, this.getX(), this.getY(), this.getX(), childlineY, PedigreeEditor.attributes.partnershipLines);
		if(numPregnancies > 1)
			editor.getPaper().circle(this.getX(), childlineY, PedigreeEditor.attributes.partnershipRadius / 2).attr({
				fill: '#47a5ad',
				stroke: '#888888',
				'stroke-width': 1,
				'opacity': 1
			});

		this._childhubConnection = editor.getPaper().setFinish();
	},
	/**
	 *
	 * @method setPos
	 * @param {Number} x 
	 * @param {Number} y 
	 * @param {Boolean} animate 
	 * @param {Function} callback 
	 */
	setPos: function($super, x, y, animate, callback) {

		this.getHoverBox().removeHandles();
		this.getHoverBox().removeButtons();

		if(animate) {
			throw "Can't animate a partnership node";
		}

		this.mark && this.mark.remove();
		this.mark2 && this.mark2.remove();

		this.getAllGraphics().transform("t " + (x - this.getX()) + "," + (y - this.getY()) + "...");
		$super(x, y, animate, callback);

		this.updatePartnerConnections();
		this.updateChildhubConnection();
		this.updateChildlessStatusLabel();
	},

	/**
	 *
	 * @method remove
	 */
	remove: function() {
		this.getJunctionShape().remove();
		this.getHoverBox().remove();
		this._idLabel && this._idLabel.remove();
		this.getChildlessShape() && this.getChildlessShape().remove();
		this.getChildlessStatusLabel() && this.getChildlessStatusLabel().remove();
		this._childhubConnection && this._childhubConnection.remove();
		this._partnerConnections && this._partnerConnections.remove();
		this.area && this.area.remove();
		this.mark && this.mark.remove();
		this.mark2 && this.mark2.remove();
	},

	/**
	 *
	 * @method getShapes
	 * @return {Raphael.st}
	 */
	getShapes: function($super) {
		return $super().push(this.getJunctionShape());
	},

	/**
	 *
	 * @method getAllGraphics
	 * @return {Raphael.st}
	 */
	getAllGraphics: function($super) {
		return editor.getPaper().set(this.getHoverBox().getBackElements(), this._idLabel, this._childlessShape).concat($super()).push(this.getHoverBox().getFrontElements());
	},

	/**
	 *
	 * @method drawLabels
	 */
	drawLabels: function() {
		// PersonVisuals.drawLabels()
	}
});

PartnershipVisuals.addMethods(ChildlessBehaviorVisuals);